const { ipcMain } = require('electron')
const net = require('net')
const dgram = require('dgram')

class TcpUdpHandler {
  constructor() {
    this.tcpClient = null
    this.tcpServer = null
    this.tcpClients = new Map()
    this.udpClient = null
    this.udpServer = null
    this.mainWindow = null
  }

  setMainWindow(window) {
    this.mainWindow = window
  }

  sendToRenderer(channel, data) {
    try {
      if (!this.mainWindow) {
        console.warn('Main window not set')
        return
      }
      
      if (this.mainWindow.isDestroyed()) {
        console.warn('Main window is destroyed')
        return
      }
      
      // 确保数据可以被序列化
      const serializedData = JSON.parse(JSON.stringify(data))
      
      // 使用webContents发送
      if (this.mainWindow.webContents) {
        this.mainWindow.webContents.send(channel, serializedData)
      } else {
        console.error('WebContents not available')
      }
    } catch (error) {
      console.error(`Failed to send data on channel ${channel}:`, error)
      console.error('Data that failed:', data)
      console.error('Error stack:', error.stack)
    }
  }

  // TCP Client Methods
  connectTcpClient(options) {
    return new Promise((resolve, reject) => {
      if (this.tcpClient) {
        this.tcpClient.destroy()
      }

      let { host, port, encoding = 'utf8' } = options
      
      // 只对 localhost 进行特殊处理，其他地址保持原样以支持外部连接
      if (host === 'localhost' || host === '::1') {
        host = '127.0.0.1'
      }
      
      this.tcpClient = new net.Socket()
      
      this.tcpClient.setEncoding(encoding)

      this.tcpClient.connect(port, host, () => {
        resolve({ success: true })
      })

      this.tcpClient.on('data', (data) => {
        this.sendToRenderer('tcp:data', {
          message: data.toString(),
          source: `${host}:${port}`,
          timestamp: Date.now()
        })
      })

      this.tcpClient.on('error', (error) => {
        this.sendToRenderer('tcp:error', { message: error.message })
        reject(error)
      })

      this.tcpClient.on('close', () => {
        this.sendToRenderer('tcp:disconnected', {})
        this.tcpClient = null
      })
    })
  }

  disconnectTcpClient() {
    if (this.tcpClient) {
      this.tcpClient.destroy()
      this.tcpClient = null
    }
    return { success: true }
  }

  sendTcpData(options) {
    const { protocol, message, target, encoding = 'utf8', lineEnding = 'none' } = options
    
    let dataToSend = message
    if (lineEnding !== 'none') {
      const endings = {
        'n': '\n',
        'rn': '\r\n',
        'r': '\r'
      }
      dataToSend += endings[lineEnding] || ''
    }

    if (protocol === 'tcp' && this.tcpClient) {
      this.tcpClient.write(dataToSend, encoding)
      return { success: true }
    } else if (protocol === 'tcp-server' && target) {
      const client = this.tcpClients.get(target)
      if (client) {
        client.write(dataToSend, encoding)
        return { success: true }
      }
    }
    
    return { success: false, error: 'No active connection' }
  }

  // TCP Server Methods
  startTcpServer(options) {
    return new Promise((resolve, reject) => {
      if (this.tcpServer) {
        this.stopTcpServer()
      }

      const { port, encoding = 'utf8' } = options
      this.tcpServer = net.createServer()

      this.tcpServer.on('connection', (socket) => {
        // 确保地址和端口都有有效值
        let remoteAddress = socket.remoteAddress || 'unknown'
        const remotePort = socket.remotePort || 0
        const timestamp = Date.now()
        
        // 处理IPv6映射的IPv4地址
        if (remoteAddress.startsWith('::ffff:')) {
          remoteAddress = remoteAddress.substring(7)
        } else if (remoteAddress === '::1') {
          remoteAddress = '127.0.0.1'
        }
        
        const clientId = `${remoteAddress}:${remotePort}:${timestamp}`
        
        // 创建一个完全干净的对象，确保可序列化
        const clientInfo = {
          id: String(clientId),
          address: String(remoteAddress),
          port: Number(remotePort)
        }
        
        this.tcpClients.set(clientId, socket)
        socket.setEncoding(encoding)

        console.log('Client connected:', clientInfo) // 调试日志
        this.sendToRenderer('tcp:client-connected', clientInfo)

        socket.on('data', (data) => {
          this.sendToRenderer('tcp:data', {
            message: data.toString(),
            source: `${clientInfo.address}:${clientInfo.port}`,
            clientId,
            timestamp: Date.now()
          })
        })

        socket.on('close', () => {
          this.tcpClients.delete(clientId)
          this.sendToRenderer('tcp:client-disconnected', clientId)
        })

        socket.on('error', (error) => {
          console.error('TCP client error:', error)
          this.tcpClients.delete(clientId)
          this.sendToRenderer('tcp:client-disconnected', clientId)
        })
      })

      this.tcpServer.on('error', (error) => {
        this.sendToRenderer('tcp:error', { message: error.message })
        reject(error)
      })

      // 监听所有网络接口 (0.0.0.0)，允许外部连接
      this.tcpServer.listen(port, '0.0.0.0', () => {
        resolve({ success: true, port })
      })
    })
  }

  stopTcpServer() {
    if (this.tcpServer) {
      this.tcpClients.forEach(socket => socket.destroy())
      this.tcpClients.clear()
      this.tcpServer.close()
      this.tcpServer = null
    }
    return { success: true }
  }

  // UDP Methods
  bindUdp(options) {
    return new Promise((resolve, reject) => {
      const { mode, port, localPort, encoding = 'utf8' } = options
      
      if (mode === 'client') {
        if (this.udpClient) {
          this.udpClient.close()
        }
        
        this.udpClient = dgram.createSocket('udp4')
        
        this.udpClient.on('message', (msg, rinfo) => {
          this.sendToRenderer('udp:data', {
            message: msg.toString(encoding),
            address: rinfo.address,
            port: rinfo.port,
            timestamp: Date.now()
          })
        })

        this.udpClient.on('error', (error) => {
          this.sendToRenderer('udp:error', { message: error.message })
          reject(error)
        })

        if (localPort) {
          this.udpClient.bind(localPort, () => {
            resolve({ success: true, port: localPort })
          })
        } else {
          this.udpClient.bind(() => {
            const address = this.udpClient.address()
            resolve({ success: true, port: address.port })
          })
        }
      } else {
        if (this.udpServer) {
          this.udpServer.close()
        }
        
        this.udpServer = dgram.createSocket('udp4')
        
        this.udpServer.on('message', (msg, rinfo) => {
          this.sendToRenderer('udp:data', {
            message: msg.toString(encoding),
            address: rinfo.address,
            port: rinfo.port,
            timestamp: Date.now()
          })
        })

        this.udpServer.on('error', (error) => {
          this.sendToRenderer('udp:error', { message: error.message })
          reject(error)
        })

        // 监听所有网络接口 (0.0.0.0)，允许外部连接
        this.udpServer.bind(port, '0.0.0.0', () => {
          resolve({ success: true, port })
        })
      }
    })
  }

  sendUdpData(options) {
    const { mode, host, port, message, encoding = 'utf8' } = options
    const buffer = Buffer.from(message, encoding)
    
    const socket = mode === 'client' ? this.udpClient : this.udpServer
    
    if (socket) {
      socket.send(buffer, port, host, (error) => {
        if (error) {
          this.sendToRenderer('udp:error', { message: error.message })
        }
      })
      return { success: true }
    }
    
    return { success: false, error: 'No active socket' }
  }

  closeUdp(mode) {
    if (mode === 'client' && this.udpClient) {
      this.udpClient.close()
      this.udpClient = null
    } else if (mode === 'server' && this.udpServer) {
      this.udpServer.close()
      this.udpServer = null
    }
    return { success: true }
  }

  cleanup() {
    this.disconnectTcpClient()
    this.stopTcpServer()
    this.closeUdp('client')
    this.closeUdp('server')
  }
}

function setupTcpUdpIPC(mainWindow) {
  const handler = new TcpUdpHandler()
  handler.setMainWindow(mainWindow)

  // TCP Client IPC handlers
  ipcMain.handle('tcp:connect', async (event, options) => {
    return await handler.connectTcpClient(options)
  })

  ipcMain.handle('tcp:disconnect', () => {
    return handler.disconnectTcpClient()
  })

  ipcMain.handle('tcp:send', (event, options) => {
    return handler.sendTcpData(options)
  })

  // TCP Server IPC handlers
  ipcMain.handle('tcp:start-server', async (event, options) => {
    return await handler.startTcpServer(options)
  })

  ipcMain.handle('tcp:stop-server', () => {
    return handler.stopTcpServer()
  })

  // UDP IPC handlers
  ipcMain.handle('udp:bind', async (event, options) => {
    return await handler.bindUdp(options)
  })

  ipcMain.handle('udp:send', (event, options) => {
    return handler.sendUdpData(options)
  })

  ipcMain.handle('udp:close', (event, mode) => {
    return handler.closeUdp(mode)
  })

  // Cleanup on window close
  mainWindow.on('closed', () => {
    handler.cleanup()
  })

  return handler
}

module.exports = {
  setupTcpUdpIPC,
  TcpUdpHandler
}